#pragma once

#include <iostream>
#include <functional>
#include <unistd.h>
#include "Err.hpp"
#include "Log.hpp"
#include "Sock.hpp"


class HttpServer;

class ThreadDate
{
public:
    ThreadDate(int sock, std::string clientIp, uint16_t clientProt, HttpServer *hs)
        : _sock(sock), _clientIp(clientIp), _clientPort(clientProt), _hs(hs)
    {
    }

public:
    int _sock;
    std::string _clientIp;
    uint16_t _clientPort;
    HttpServer *_hs;
};

using func_t = std::function<std::string(std::string)>;
static uint16_t defaultport = 8888;


class HttpServer
{
public:
    HttpServer(func_t func,uint16_t port = defaultport) : _port(port),_func(func)
    {
    }

    // 初始化服务器
    void InitServer()
    {
        _listenSock.Socket();
        _listenSock.Bind(_port);
        _listenSock.Listen();

        logMessage(Info, "init server sucess,listenSock:%d", _listenSock.Fd());
    }

    void HandlerHttpRequest(int sock)
    {
        char buffer[4096];
        std::string request;
        int n=recv(sock,buffer,sizeof(buffer)-1,0);
        if(n<=0)
        {
            logMessage(Info,"client quit...");
        }
        else 
        {
            buffer[n]='\0';
            request=buffer;
            std::string responce=_func(request);
            send(sock,responce.c_str(),responce.size(),0);
        }
    }

    // 线程启动函数
    static void *ThreadRoutine(void *args)
    {
        pthread_detach(pthread_self()); // 线程分离
        ThreadDate *td = static_cast<ThreadDate *>(args);
        td->_hs->HandlerHttpRequest(td->_sock);

        close(td->_sock);
        delete td;
        return nullptr;
    }

    void Start()
    {
        while (true)
        {
            std::string clientIp;
            uint16_t clientPort;
            int sock = _listenSock.Accept(clientIp, clientPort);
            if (sock < 0)
            {
                logMessage(Warning, "Accept client error");
            }

            ThreadDate *td = new ThreadDate(sock, clientIp, clientPort, this);
            pthread_t tid;
            pthread_create(&tid, nullptr, ThreadRoutine, td);
        }
    }

    ~HttpServer()
    {
    }

private:
    uint16_t _port;
    Sock _listenSock;
    func_t _func;
};